#include "TerminadorPartidas.h"

TerminadorPartidas::TerminadorPartidas(bool atachado) :
		Thread(atachado) {
	this->torneo = NULL;
}

TerminadorPartidas::~TerminadorPartidas() {
}


void TerminadorPartidas::signalHandler(int signal){
	switch (signal){
	case SIGUSR1:
		pthread_exit(NULL);
	}
}

void TerminadorPartidas::run() {
	signal(SIGUSR1, TerminadorPartidas::signalHandler);
	while (!this->torneo->isFinalizado()) {
		this->torneo->getMutexPartidas()->P();
		std::list<t_partida>::iterator iteradorPartidas = this->torneo->getPartidas().begin();
		int status = 0;
		for (; iteradorPartidas  != this->torneo->getPartidas().end(); ++iteradorPartidas) {
			if(iteradorPartidas->activo){
				int partidaId = (int) iteradorPartidas->partidaId;
				/* Me fijo si ya libero */
				if (waitpid(partidaId, &status, WNOHANG) > 0) {
					/* Ahora verifico si los jugadores siguen activos, de ser asi los vuelvo a encolar en la lista de jugadores disponibles */
					t_partida tmp = this->torneo->getAdministradorMemoriaCompartida()->leerDatos(partidaId);
					/* Por cada jugador, si sigue conectado les aviso el fin de la partida y los vuelvo a enlistar como disponibles */
					if(tmp.jugador1.conectado){
						this->torneo->notificarFinPartida(iteradorPartidas->jugador1.socket_id);
						this->torneo->enlistarJugadorDisponible(&tmp.jugador1);
					}
					if(tmp.jugador2.conectado){
						this->torneo->notificarFinPartida(iteradorPartidas->jugador2.socket_id);
						this->torneo->enlistarJugadorDisponible(&tmp.jugador2);
					}
					/* Ahora libero la memoria compartida */
					this->torneo->getAdministradorMemoriaCompartida()->cerrarShm(iteradorPartidas->partidaId);
					this->torneo->getAdministradorMemoriaCompartida()->eliminarSemaforo(iteradorPartidas->partidaId);
					/* La seteo como inactiva */
					iteradorPartidas->activo = false;
					/* Decremento la cantidad de partidas */
					torneo->decPartidas();
				} else {
					/*Si no libero, me fijo si no esta corriendo, de ser así es porque la mataron a mano y no la tome todavia */
					if(kill(partidaId, 0) == -1){
						/* notifico a sus jugadores el fin del torneo */
						this->torneo->notificarFinTorneo(true, iteradorPartidas->jugador1.socket_id);
						this->torneo->notificarFinTorneo(true, iteradorPartidas->jugador2.socket_id);
						this->torneo->getSocket()->closeSocket(iteradorPartidas->jugador1.socket_id);
						this->torneo->getSocket()->closeSocket(iteradorPartidas->jugador2.socket_id);
						/* Ahora libero la memoria compartida */
						this->torneo->getAdministradorMemoriaCompartida()->cerrarShm(iteradorPartidas->partidaId);
						this->torneo->getAdministradorMemoriaCompartida()->eliminarSemaforo(iteradorPartidas->partidaId);
						/* La seteo como inactiva */
						iteradorPartidas->activo = false;
						/* Decremento la cantidad de partidas */
						torneo->decPartidas();
						/* Logueo */
						cout << "[TORNEO] - [ERROR] - Se murio una partida con -9" << endl;
						/* Si ya no esta corriendo es porque la mataron a mano, entonces finalizo el torneo */
						kill(getpid(), SENIAL_FIN_DAEMON);
					}
				}
			}
		}
		this->torneo->getMutexPartidas()->V();
		usleep(100000);
	}
	pthread_exit(0);
}

Torneo* TerminadorPartidas::getTorneo() {
	return torneo;
}

void TerminadorPartidas::setTorneo(Torneo* torneo) {
	this->torneo = torneo;
}

